<template>
  <div>
    <a-modal
      v-model:open="open"
      title="AI扩图"
      :footer="false"
      @cancel="handleCancel"
      class="pic-ai-handle"
    >
      <a-row :gutter="16">
        <a-col span="12">
          <h4>原始图片</h4>
          <a-image :src="props.picture?.url" style="max-width: 100%"></a-image>
        </a-col>
        <a-col span="12">
          <h4>扩图结果</h4>
          <a-image
            v-if="aiHandleResUrl"
            :src="aiHandleResUrl"
            :alt="props.picture?.name"
            style="max-width: 100%"
          ></a-image>
        </a-col>
      </a-row>
      <div style="margin-top: 16px"></div>
      <a-button type="primary" ghost @click="doAIHandler" :loading="loading">生成图片</a-button>
      <a-button type="primary" @click="saveResult" style="margin-left: 8px" :loading="saveLoading"
        >保存结果
      </a-button>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { onUnmounted, ref } from 'vue'
import {
  createPicHandletaskUsingPost,
  queryPicHandletaskUsingGet,
  urlUploadPictureUsingPost,
} from '@/api/fileController.ts'
import { message } from 'ant-design-vue'

//控制是否打开
const open = ref<boolean>(false)

interface Props {
  //空间id
  spaceId?: number
  //图片对象
  picture?: API.PictureVO
  //上传成功之后的回调
  onSuccess: (newPicture: API.PictureVO) => void
}

const props = defineProps<Props>()

const loading = ref<boolean>(false)
const saveLoading = ref<boolean>(false)
//ai处理后的图片url
const aiHandleResUrl = ref<string>()
//记录taskId
const taskId = ref<string>()
//轮询定时器
let pollingTimer: NodeJS.Timeout = null

/**-
 * 生成图片 调用后端创建AI处理图片任务接口
 */
async function doAIHandler() {
  loading.value = true
  const resp = await createPicHandletaskUsingPost({
    pictureId: props.picture?.id,
    parameters: {
      xScale: 2,
      yScale: 2,
    },
  })
  if (resp.data.code === 0) {
    message.success('后台处理中，请勿关闭窗口，稍后查证')
    //记录任务ID
    taskId.value = resp.data.data?.output?.taskId
    //开启任务轮询
    startPolling()
  } else {
    message.error(resp.data.message)
  }
}

/**
 * 开启轮询
 */
const startPolling = () => {
  if (!taskId.value) {
    return
  }
  pollingTimer = setInterval(async () => {
    try {
      //调用后端查询AI处理图片任务结果的接口
      const resp = await queryPicHandletaskUsingGet({
        taskId: taskId.value,
      })
      //接口成功
      if (resp.data.code === 0) {
        console.log(resp.data.data?.output?.taskStatus)
        //成功
        if (resp.data.data?.output?.taskStatus === 'SUCCEEDED') {
          aiHandleResUrl.value = resp.data.data?.output?.outputImageUrl
          stopPolling()
        }
        //失败
        if (resp.data.data?.output?.taskStatus === 'FAILED') {
          stopPolling()
        }
      } //接口失败
      else {
        stopPolling()
      }
    } catch (error) {
      console.log('调用后端查询AI处理图片任务结果的接口错误', error)
      stopPolling()
    }
  }, 3000)
}

/**
 * 结束轮询
 */
function stopPolling() {
  if (pollingTimer) {
    clearInterval(pollingTimer)
    loading.value = false
    pollingTimer = null
    taskId.value = null
  }
}

/**
 * 保存结果
 */
async function saveResult() {
  saveLoading.value = true

  let id = ''
  if (props.picture) {
    id = props.picture.id
  }
  //这里的picture对象，是父组件传递过来的
  const params: API.PictureUploadRequest = {
    id: id,
    url: aiHandleResUrl.value,
    spaceId: props.spaceId,
  }
  const resp = await urlUploadPictureUsingPost(params)
  if (resp.data.code === 0 && resp.data.data) {
    message.success('图片上传成功')
    //将上传成功的图片信息传递给父组件
    //关闭模态框
    handleCancel()
    //子组件在图片上传成功后，通过 props.onSuccess?.(resp.data.data) 调用该回调，将新的图片信息传递回父组件
    props.onSuccess?.(resp.data.data)
  } else if (resp.data.code === 40100) {
    message.error('图片上传失败：' + resp.data.message)
  } else {
    message.error('图片上传错误：' + resp.data.message)
  }
  saveLoading.value = false
}

/**
 * 关闭
 * @param e
 */
const handleCancel = () => {
  open.value = false
}

/**
 * 打开
 */
const handleOpen = () => {
  open.value = true
}

/**
 * 暴露给父组件
 */
defineExpose({
  handleOpen,
})

onUnmounted(() => {
  stopPolling()
})
</script>

<style>
.pic-ai-handle {
  text-align: center;
}
</style>
